package com.redis.RedisConfigProxy;

import org.springframework.data.redis.listener.ChannelTopic;
import org.springframework.data.redis.listener.Topic;
import sun.plugin2.message.Message;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.List;

/**
 * @description: TODO
 * @date 2021/10/15 11:01
 */
public class MessageListenInvocationHandler  implements InvocationHandler {

    private RedisListenInfo redisListenInfo;

    public MessageListenInvocationHandler(RedisListenInfo redisListenInfo) {
        this.redisListenInfo = redisListenInfo;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (!method.getName().equals("onMessage")) {
            // 由于 RedisMessageListenerContainer 在存MessageListener的时候直接用对象,容器是HashMap所以会调用hashCode
            if (method.getName().equals("hashCode")) {
                return hashCode();
            } else {
                return 1;
            }
        }
        List<Class<?>> parameterTypes = redisListenInfo.getParameterTypes();
        Method targetMethod = redisListenInfo.getMethod();
        if (parameterTypes == null || parameterTypes.isEmpty()) {
            return targetMethod.invoke(redisListenInfo.getObject());
        } else {
            Object[] params = new Object[parameterTypes.size()];
            for (int i = 0; i < parameterTypes.size(); i++) {
                Class<?> aClass = parameterTypes.get(i);
                params[i] = getMethodParam(aClass, args);
            }
            return targetMethod.invoke(redisListenInfo.getObject(), params);
        }
    }

    public Object getMethodParam(Class<?> paramType, Object[] args) {
        if (paramType.isAssignableFrom(String.class)) {
            return args[0].toString();
        } else if (paramType.isAssignableFrom(Message.class)) {
            return args[0];
        } else if (paramType.isAssignableFrom(byte[].class)) {
            return args[1];
        } else if (paramType.isAssignableFrom(Topic.class)) {
            return new ChannelTopic(new String((byte[]) args[1]));
        } else {
            return null;
        }
    }
}
